---
title: 레이아웃
description: Astro 레이아웃 소개
i18nReady: true
---

import ReadMore from '~/components/ReadMore.astro'

**레이아웃**은 페이지 템플릿과 같은 재사용 가능한 UI 구조를 제공하는 데 사용되는 [Astro 컴포넌트](/ko/basics/astro-components/)입니다.

우리는 일반적으로 머리글, 탐색 모음, 바닥글과 같이 페이지 전체에서 공유되는 공통 UI 요소를 제공하는 Astro 컴포넌트에 대해 "레이아웃"이라는 용어를 사용합니다. 일반적인 Astro 레이아웃 컴포넌트는 다음과 같은 [Astro, Markdown, MDX 페이지](/ko/basics/astro-pages/)를 제공합니다.
- **페이지 셸**(`<html>`, `<head>`, `<body>` 태그)
- 개별 페이지 콘텐츠를 삽입해야 하는 위치를 지정하는 [**`<slot />`**](/ko/basics/astro-components/#슬롯).

하지만 레이아웃 컴포넌트에는 특별한 것이 없습니다! 다른 Astro 컴포넌트처럼 [props를 전달](/ko/basics/astro-components/#컴포넌트-props)받고 [다른 컴포넌트를 가져와 사용](/ko/basics/astro-components/#컴포넌트-구조)할 수 있습니다. 여기에는 [UI 프레임워크 컴포넌트](/ko/guides/framework-components/)와 [클라이언트 측 스크립트](/ko/guides/client-side-scripts/)가 포함될 수 있습니다. 전체 페이지 셸을 제공할 필요도 없으며 대신 부분 UI 템플릿으로 사용할 수 있습니다.

그러나 레이아웃 컴포넌트에 페이지 셸이 포함되어 있는 경우 `<html>` 요소는 컴포넌트에 있는 다른 모든 요소의 상위 요소여야 합니다.

레이아웃 컴포넌트는 일반적으로 프로젝트의 `src/layouts` 디렉터리에 배치되지만 이는 필수 사항은 아닙니다. 프로젝트의 어느 곳에나 배치하도록 선택할 수 있습니다. 심지어 [레이아웃 이름 앞에 `_`를 붙이면](/ko/guides/routing/#페이지-제외) 레이아웃 컴포넌트와 페이지를 같은 위치에 배치할 수도 있습니다.

## 레이아웃 예시

```astro "<slot />" 
---
// src/layouts/MySiteLayout.astro
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
const { title } = Astro.props;
---
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <BaseHead title={title}/>
  </head>
  <body>
    <nav>
      <a href="#">홈</a>
      <a href="#">블로그</a>
      <a href="#">연락처</a>
    </nav>
    <h1>{title}</h1>
    <article>
      <slot /> <!-- 콘텐츠가 여기에 삽입됩니다. -->
    </article>
    <Footer />
  </body>
  <style>
    h1 {
      font-size: 2rem;
    }
  </style>
</html>
```

```astro title="src/pages/index.astro"
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="Home Page">
  <p>레이아웃으로 감싼 페이지입니다!</p>
</MySiteLayout>
```

<ReadMore>[슬롯](/ko/basics/astro-components/#슬롯)에 대해 자세히 알아보세요.</ReadMore>

## 레이아웃에 TypeScript 사용

모든 Astro 레이아웃이 props의 타입을 제공하도록 수정되면 타입 안전 및 자동 완성 기능을 도입할 수 있습니다:

```astro ins={2-7} title="src/components/MyLayout.astro"
---
interface Props { 
  title: string;
  description: string;
  publishDate: string;
  viewCount: number;
}
const { title, description, publishDate, viewCount } = Astro.props;
---
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="description" content={description}>
    <title>{title}</title>
  </head>
  <body>
    <header>
      <p>Published on {publishDate}</p>
      <p>Viewed by {viewCount} folks</p>
    </header>
    <main>
      <slot />
    </main>
  </body>
</html>
```

## Markdown 레이아웃

페이지 레이아웃은 페이지 형식이 없는 개별 Markdown 페이지에 특히 유용합니다.

Astro는 특별한 `layout` 프런트매터 속성을 제공하는데, 이는 [파일 기반 라우팅을 사용하는 `src/pages/`의 개별 `.md` 파일](/ko/guides/markdown-content/#개별-markdown-페이지)에서 페이지 레이아웃으로 사용할 `.astro` 컴포넌트를 지정하기 위한 것입니다. 이 컴포넌트를 사용하면 메타 태그(예: `<meta charset="utf-8">`)와 같은 `<head>` 콘텐츠와 Markdown 페이지를 위한 스타일을 제공할 수 있습니다. 기본적으로 이 지정된 컴포넌트는 Markdown 파일의 데이터에 자동으로 접근할 수 있습니다.

[콘텐츠 컬렉션](/ko/guides/content-collections/)을 사용하여 콘텐츠를 쿼리하고 렌더링할 때는 이것이 특별한 속성으로 인식되지 않습니다.

```markdown title="src/pages/page.md" {2} 
---
layout: ../layouts/BlogPostLayout.astro
title: "안녕하세요!"
author: "Matthew Phillips"
date: "09 Aug 2022"
---
모든 프런트매터 속성은 Astro 레이아웃 컴포넌트에 대한 props로 사용할 수 있습니다.

`layout` 속성은 Astro에서 제공하는 유일한 특수 속성입니다.

이는 `src/pages/` 디렉터리에 있는 Markdown 파일에서 사용할 수 있습니다.

```

Markdown 페이지의 일반적인 레이아웃은 다음과 같습니다.

1. Markdown 페이지의 프런트매터 및 기타 데이터를 사용하기 위한 `frontmatter` prop.
2. 페이지의 Markdown 콘텐츠가 렌더링되어야 하는 위치를 나타내는 기본 [`<slot />`](/ko/basics/astro-components/#슬롯).

```astro title="src/layouts/BlogPostLayout.astro" /(?<!//.*){?frontmatter(?:\\.\w+)?}?/ "<slot />"
---
// 1. 프런트매터 prop을 통해 프런트매터 및 기타 데이터를 사용할 수 있습니다.
const { frontmatter } = Astro.props;
---
<html>
  <head>
    <!-- 여기에 스타일, 메타 태그 등 다른 Head 요소를 추가하세요. -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <!-- 일반적인 머리글 및 바닥글과 같은 다른 UI 컴포넌트를 여기에 추가합니다. -->
    <h1>{frontmatter.title} by {frontmatter.author}</h1>
    <!-- 2. 렌더링된 HTML은 기본 슬롯으로 전달됩니다. -->
    <slot />
    <p>작성: {frontmatter.date}</p>
  </body>
</html>
```

`MarkdownLayoutProps` 도우미를 사용하여 레이아웃의 [`Props` 타입](/ko/guides/typescript/#컴포넌트-props)을 설정할 수 있습니다.

```astro title="src/layouts/BlogPostLayout.astro" ins={2,4-9}
---
import type { MarkdownLayoutProps } from 'astro';

type Props = MarkdownLayoutProps<{
  // 여기서 프런트매터 props를 정의하세요.
  title: string;
  author: string;
  date: string;
}>;

// 이제 'frontmatter', 'url' 및 기타 Markdown 레이아웃 속성에 타입 안전성을 적용하여 사용할 수 있습니다.
const { frontmatter, url } = Astro.props;
---
<html>
  <head>
    <meta charset="utf-8">
    <link rel="canonical" href={new URL(url, Astro.site).pathname}>
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <h1>{frontmatter.title} - {frontmatter.author}</h1>
    <slot />
    <p>작성: {frontmatter.date}</p>
  </body>
</html>
```

### Markdown 레이아웃 Props

Markdown 레이아웃은 `Astro.props`를 통해 다음 정보를 사용할 수 있습니다.

- **`file`** - 이 파일의 절대 경로 (예: `/home/user/projects/.../file.md`).
- **`url`** - 해당 페이지의 URL (예: `/en/guides/markdown-content`).
- **`frontmatter`** - Markdown 또는 MDX 문서의 모든 프런트매터.
  - **`frontmatter.file`** - 최상위 `file` 속성과 동일합니다.
  - **`frontmatter.url`** - 최상위 `url` 속성과 동일합니다.
- **`headings`** - 관련 메타데이터가 있는 Markdown 또는 MDX 문서의 제목(`h1 -> h6`)들의 목록입니다. 이 목록은 다음 타입을 따릅니다: `{ depth: number; slug: string; text: string }[]`
- **`rawContent()`** - 원시 Markdown 문서를 문자열로 반환하는 함수입니다.
- **`compiledContent()`** - HTML 문자열로 컴파일된 Markdown 문서를 반환하는 비동기 함수입니다.

:::note
Markdown 레이아웃은 `Astro.props`를 통해 모든 Markdown 파일에서 [사용 가능한 속성들](/ko/guides/markdown-content/#사용-가능한-속성)을 사용할 수 있지만 **두 가지 차이점이 있습니다**.

* 제목 정보(예: `h1 -> h6` 요소)는 `getHeadings()` 함수가 아닌 `headings` 배열을 통해 사용할 수 있습니다.

* *또한* `file` 및 `url`은  중첩된 `frontmatter` 속성(예: `frontmatter.url` 및 `frontmatter.file`)으로 사용할 수도 있습니다.

:::

### 수동으로 레이아웃 가져오기 (MDX)

또한 같은 방식으로, MDX 파일의 프런트매터에 있는 특수 Markdown layout 속성을 사용하여 `frontmatter` 및 `headings` props를 지정된 레이아웃 컴포넌트에 직접 전달할 수도 있습니다. 

프런트매터에 존재하지 않거나 존재할 수 없는 정보를 MDX 레이아웃에 전달하려면 대신 `<Layout />` 컴포넌트를 가져와 사용할 수 있습니다. 이는 다른 Astro 컴포넌트처럼 작동하며 props를 자동으로 받지 않습니다. 필요한 props는 직접 전달하세요:

```mdx title="src/pages/posts/first-post.mdx" ins={6} del={2} /</?BaseLayout>/ /</?BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>/
---
layout: ../../layouts/BaseLayout.astro
title: '나의 첫 MDX 게시물'
publishDate: '21 September 2022'
---
import BaseLayout from '../../layouts/BaseLayout.astro';

export function fancyJsHelper() {
  return "YAML로 시도해 보세요!";
}

<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>
  MDX를 사용하는 새 Astro 블로그에 오신 것을 환영합니다!
</BaseLayout>
```

그러면 레이아웃의 `Astro.props`를 통해 값을 사용할 수 있으며 MDX 콘텐츠는 `<slot />` 컴포넌트가 작성된 페이지에 삽입됩니다.

```astro title="src/layouts/BaseLayout.astro" /{?title}?/ "fancyJsHelper" "{fancyJsHelper()}"
---
const { title, fancyJsHelper } = Astro.props;
---
<html>
  <head>
    <!-- -->
    <meta charset="utf-8">
  </head>
  <body>
    <!-- -->
    <h1>{title}</h1>
    <slot /> <!-- 콘텐츠는 여기에 삽입됩니다. -->
    <p>{fancyJsHelper()}</p>
    <!-- -->
  </body>
</html>
```

어떤 레이아웃을 사용할 때(프런트매터 `layout` 속성을 통해서든 레이아웃을 가져오든), 레이아웃에 `<meta charset="utf-8">` 태그를 반드시 포함해야 합니다. Astro가 더 이상 MDX 페이지에 이를 자동으로 추가하지 않기 때문입니다.

<ReadMore>[Markdown/MDX 가이드](/ko/guides/markdown-content/)에서 Astro의 Markdown 및 MDX 지원에 대해 자세히 알아보세요.</ReadMore>

## 중첩 레이아웃

레이아웃 컴포넌트는 HTML의 전체 페이지를 포함할 필요가 없습니다. 레이아웃을 더 작은 컴포넌트로 나누고 레이아웃 컴포넌트를 결합하여 더욱 유연한 페이지 템플릿을 만들 수 있습니다. 이 패턴은 여러 레이아웃에서 일부 코드를 공유하려는 경우에 유용합니다.

예를 들어, `BlogPostLayout.astro` 레이아웃 컴포넌트는 게시물의 제목, 날짜, 작성자의 스타일을 지정할 수 있습니다. 그리고 사이트 전체 `BaseLayout.astro`가 탐색, 바닥글, SEO 메타 태그, 전역 스타일, 글꼴과 같은 페이지 템플릿의 나머지 부분을 처리할 수 있습니다. 또한, 다른 중첩 컴포넌트와 마찬가지로 게시물에서 받은 props를 다른 레이아웃으로 전달할 수도 있습니다.

```astro {3} /</?BaseLayout>/ /</?BaseLayout url={frontmatter.url}>/
---
// src/layouts/BlogPostLayout.astro
import BaseLayout from './BaseLayout.astro';
const { frontmatter } = Astro.props;
---
<BaseLayout url={frontmatter.url}>
  <h1>{frontmatter.title}</h1>
  <h2>게시물 작성자: {frontmatter.author}</h2>
  <slot />
</BaseLayout>
```
